﻿using Edu.Entitys;
using Edu.Services;
using Edu.Utilities;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;

namespace Edu.Abstracts
{







    public enum AchievementTypes
    {
        [Description("1ffbff60-2cab-1504-0122-39ee6da8c11a")]
        快马加鞭,
        [Description("45f0dc00-9c55-09dd-8d63-39ee6da9651c")]
        师门之傲,
        [Description("70df0fbe-a2ad-3272-f43e-39ee6da9b178")]
        能力高阶,
        [Description("8d190fe4-0355-55eb-1da0-39ee6da926f7")]
        学霸上线,
        [Description("b5ee1f41-29ff-c550-6fe4-39ee6da84b38")]
        好好学习,
        [Description("eb762575-6448-a092-c174-39ee6daae7a7")]
        荣誉勋章,




        [Description("01c6e05a-6686-0047-e5bc-39ee6dab3d8e")]
        教导有方,
        [Description("02864714-150a-7608-34cb-39ee6dab999c")]
        诲人不倦,
        [Description("4f4e6b36-8cf8-b085-c08d-39ee6daa9a2e")]
        良师益友,
        [Description("f778f7a5-0853-c473-21bd-39ee6daa1929")]
        桃李天下
    }








    public class AchievementFilterAttribute : ActionFilterAttribute
    {
        private readonly IAppUserRepository _userRepository;
        private IRepository<AppStudent, Guid> appStudents;
        private IRepository<AppStudyTask, Guid> appStudyTasks;
        private IRepository<AppUserAchievement, Guid> appUserAchievements;
        private ILogger<AchievementFilterAttribute> logger;

        public AchievementFilterAttribute(
            IAppUserRepository userRepository,
            IRepository<AppStudyTask, Guid> appStudyTasks,
            IRepository<AppStudent, Guid> appStudents,
            IRepository<AppUserAchievement, Guid> appUserAchievements,
            ILogger<AchievementFilterAttribute> logger
            )
        {
            this.appStudents = appStudents;
            this.appStudyTasks = appStudyTasks;
            this.appUserAchievements = appUserAchievements;
            this._userRepository = userRepository;
            this.logger = logger;
        }


        public async override Task OnActionExecutionAsync(
            ActionExecutingContext context,
            ActionExecutionDelegate next)
        {
            if (!ShouldSaveAchievement(context))
            {
                await next();
                return;
            }

            try
            {
                var result = await next();
                if (result.Exception != null && !result.ExceptionHandled)
                {
                    return;
                }
            }
            catch (Exception)
            {
                throw;
            }

            await this.Handler(context);
        }

        private async Task Handler(ActionExecutingContext context)
        {

            try
            {
                var controllerActionDescriptor = context.ActionDescriptor.AsControllerActionDescriptor();
                var actionArguments = context.ActionArguments;

                if (controllerActionDescriptor.ControllerName == "StudyTask" && controllerActionDescriptor.ActionName == "UpdateStatus")
                {
                    var scroeDto = actionArguments["dto"] as TaskPostStatusDto;
                    var studyTask = await this.appStudyTasks.GetAsync(scroeDto.Id);

                    if (studyTask.Status == StudyTaskStatus.Complete)
                    {
                        var student = this.appStudents.FirstOrDefault(a => a.UserId == studyTask.StudentId);

                        await this.haohaoxuexi(studyTask);

                        await this.kuaimajiabian(studyTask);

                        await this.xuebashangxian(studyTask, student);

                        await this.huirenbujuan(studyTask);

                        await this.nengligaojie(studyTask);

                        await this.rongyuxunzhang(studyTask);
                    }

                    if (studyTask.Status == StudyTaskStatus.UnScore)
                    {
                        await this.jiaodaoyoufang(studyTask);
                    }

                }


                if (controllerActionDescriptor.ControllerName == "Rating")
                {

                    if (controllerActionDescriptor.ActionName == "ToStudent")
                    {
                        await this.shimenzhiao(actionArguments["inDto"] as RatingInDto);
                    }

                    if (controllerActionDescriptor.ActionName == "ToTeacher")
                    {
                        await this.liangshiyiyou(actionArguments["inDto"] as RatingInDto);
                    }
                }

                if (controllerActionDescriptor.ControllerName == "Admin" && controllerActionDescriptor.ActionName == "UpdateGrad")
                {
                    await this.taolitianxia(actionArguments["dto"] as GradStudentDto);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogException(ex);
            }
        }

        private async Task jiaodaoyoufang(AppStudyTask studyTask)
        {
            if (studyTask.TeacherScore != 5)
            {
                return;
            }

            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.教导有方));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.TeacherId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.Progress++;
            if (achievement.Progress >= 10)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }

            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        private async Task rongyuxunzhang(AppStudyTask studyTask)
        {
            if (studyTask.Score != 5)
            {
                return;
            }

            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.荣誉勋章));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.StudentId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.Progress++;
            if (achievement.Progress >= 10)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }

            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        private async Task nengligaojie(AppStudyTask studyTask)
        {
            if (studyTask.Score != 5)
            {
                return;
            }

            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.能力高阶));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.StudentId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.CreatedTime = DateTimeOffset.UtcNow;

            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        //累计10名徒弟出师
        private async Task taolitianxia(GradStudentDto dto)
        {
            if (dto.Status != StudentStatus.Grad)
            {
                return;
            }
            var student = this._userRepository.Where(a => a.PhoneNumber == dto.PhoneNumber && a.Name == dto.Name).SingleOrDefault();
            var appStudent = this.appStudents.Where(a => a.UserId == student.Id).Single();
            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.桃李天下));
            var achievement = await this.GetOrAddUserAchievement(guid, appStudent.TeacherId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.Progress++;
            if (achievement.Progress >= 10)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        //被至少三名徒弟评分5星
        private async Task liangshiyiyou(RatingInDto ratingInDto)
        {
            if (ratingInDto.Score != 5)
            {
                return;
            }
            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.良师益友));
            var achievement = await this.GetOrAddUserAchievement(guid, ratingInDto.TargetId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.Progress++;
            if (achievement.Progress >= 3)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        //被师傅评价5星 师门之傲
        private async Task shimenzhiao(RatingInDto ratingInDto)
        {
            if (ratingInDto.Score != 5)
            {
                return;
            }

            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.师门之傲));
            var achievement = await this.GetOrAddUserAchievement(guid, ratingInDto.TargetId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.CreatedTime = DateTimeOffset.UtcNow;
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }



        //所有徒弟中,累积提前60天完成学习任务  诲人不倦
        private async Task huirenbujuan(AppStudyTask studyTask)
        {
            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.诲人不倦));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.TeacherId);
            if (achievement.CreatedTime != null)
            {
                return;
            }

            var days = (studyTask.DeadLine - studyTask.CompleteTime.Value).Days;

            if (days <= 0)
            {
                return;
            }
            achievement.Progress += days;

            if (achievement.Progress >= 60)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }



        //两个季度的得分均超过四星   学霸上线
        private async Task xuebashangxian(AppStudyTask studyTask, AppStudent student)
        {
            var joinDate = new DateTimeOffset(student.JoinYear, student.JoinQuarter * 3 - 2, 1, 0, 0, 0, TimeSpan.Zero);
            var date = DateTimeOffset.UtcNow;

            var months = ((date.Year - joinDate.Year) * 12) + date.Month - joinDate.Month;
            //小于两个季度不计算
            if (months < 6)
            {
                return;
            }

            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.学霸上线));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.StudentId);
            if (achievement.CreatedTime != null)
            {
                return;
            }

            var currentQ = date.GetQuarter();
            var currentY = date.Year;

            var progress = 0;

            for (int i = currentY; i >= student.JoinYear; i--)
            {
                for (int j = currentQ - 1; j > 0; j--)
                {
                    var tasks = appStudyTasks.Where(a => a.StudentId == student.UserId && a.Year == i && a.Quarter == j && a.Status == StudyTaskStatus.Complete).ToList();

                    if (tasks.Count == 0)
                    {
                        continue;
                    }

                    var allScore = 0;
                    foreach (var item in tasks)
                    {
                        allScore += item.Score ?? 0;
                    }

                    if (allScore / tasks.Count >= 4)
                    {
                        progress++;
                    }

                    if (progress >= 2)
                    {
                        break;
                    }
                }
                currentQ = 5;

                if (progress >= 2)
                {
                    break;
                }
            }

            if (progress < 2)
            {
                return;
            }

            achievement.CreatedTime = DateTimeOffset.UtcNow;
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }




        //累积提前20天完成学习任务  快马加鞭
        private async Task kuaimajiabian(AppStudyTask studyTask)
        {
            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.快马加鞭));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.StudentId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            var days = (studyTask.DeadLine - studyTask.CompleteTime.Value).Days;

            if (days <= 0)
            {
                return;
            }
            achievement.Progress += days;

            if (achievement.Progress >= 20)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }

        //累计完成30个学习任务  好好学习
        private async Task haohaoxuexi(AppStudyTask studyTask)
        {
            var guid = Guid.Parse(EnumUtils.StringValueOf(AchievementTypes.好好学习));
            var achievement = await this.GetOrAddUserAchievement(guid, studyTask.StudentId);
            if (achievement.CreatedTime != null)
            {
                return;
            }
            achievement.Progress++;
            if (achievement.Progress >= 30)
            {
                achievement.CreatedTime = DateTimeOffset.UtcNow;
            }
            await this.appUserAchievements.UpdateAsync(achievement, autoSave: true);
        }



        public async Task<AppUserAchievement> GetOrAddUserAchievement(Guid achievementId, Guid userId)
        {
            var result = this.appUserAchievements.Where(s => s.AchievementId == achievementId && s.UserId == userId)
                .FirstOrDefault();

            if (result == null)
            {
                result = await this.appUserAchievements.InsertAsync(new AppUserAchievement()
                {
                    Id = Guid.NewGuid(),
                    UserId = userId,
                    Progress = 0,
                    AchievementId = achievementId
                }, true);
            }
            return result;
        }

        private bool ShouldSaveAchievement(ActionExecutingContext context)
        {
            if (!context.ActionDescriptor.IsControllerAction())
            {
                return false;
            }
            var methodInfo = context.ActionDescriptor.GetMethodInfo();

            if (methodInfo == null)
            {
                return false;
            }
            if (!methodInfo.IsPublic)
            {
                return false;
            }

            return true;
        }
    }
}
